home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Applications… / QuickDraw GX Aware Sample ƒ / Simple Sample ƒ / menus & windows.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  20.6 KB  |  830 lines  |  [TEXT/MMCC]

  1. /*********************************************************************
  2.  
  3.     menus & windows.c
  4.     
  5.     This file contains the menu and window handling code for the
  6.     QuickDraw GX unaware sample, "Simple Sample."
  7.  
  8.     Additional info can be found in the related develop #19 article,
  9.     "Adding QuickDraw GX Printing to QuickDraw Applications."
  10.  
  11.     Dave Hersey, Apple Developer Technical Support.
  12.     
  13.     ——————— Edit Trail ———————
  14.     
  15.     constructed:                                    1/22/94  - dmh
  16.     cleaned up for 2nd draft of develop article:    3/10/94  - dmh
  17.     cleaned up for final:                            4/14/94  - dmh
  18.     removed sprintf calls, to avoid need for ANSI   8/16/94  - nick
  19.     added NewGXPrintingEventProc to build 
  20.     descriptors for ppc                             8/17/94  - nick
  21.     
  22. *********************************************************************/
  23.  
  24. #include "Simple Sample.h"
  25.  
  26.  
  27. /************************************************************
  28.   MyCreateDocument - This routine is called to create a new
  29.   document.
  30.  
  31. *************************************************************/
  32.  
  33. OSErr MyCreateDocument(char *docTitle, MyDocumentPtr *createdDocument)
  34. {
  35.     OSErr            err;
  36.     WindowPtr        documentWindow;
  37.     long            newPage;
  38.  
  39.     *createdDocument = nil;
  40.  
  41. // Create a window for our document.
  42.  
  43.     documentWindow = (WindowPtr) NewCWindow(nil, &gWindowRect, (ConstStr255Param) docTitle, false, noGrowDocProc, (WindowPtr)-1L, true, 0L);
  44.     require_action(documentWindow, CouldNotCreateWindow, err = MemError(););
  45.  
  46. // Initialize our private data for the document.
  47.  
  48.     *createdDocument = (MyDocumentPtr) NewPtrClear(sizeof(MyDocumentRec));
  49.     require_action(*createdDocument, CouldNotCreateDocRec, err = MemError(););
  50.  
  51. //    Create a print handle.
  52.  
  53.     (*createdDocument)->documentPrintHdl = (THPrint) NewHandle(sizeof(TPrint));
  54.     err = MemError();
  55.  
  56.     if (!err)
  57.     {
  58.         PrOpen();
  59.         PrintDefault((*createdDocument)->documentPrintHdl);
  60.         PrClose();
  61.     }
  62.  
  63. /*
  64.     If there were no errors, add 1 page to the document, and
  65.     store a reference to our private data in the document's
  66.     window's refCon field.
  67. */
  68.     nrequire(err, CouldNotCreatePrintStuff);
  69.     
  70.     (*createdDocument)->numPages = 0;
  71.     (*createdDocument)->documentWindow = documentWindow;
  72.     (*createdDocument)->documentFSSpec.name[0] = 0;        // Indicates that document has never
  73.                                                         // been saved.
  74.     if (docTitle[0] > 31)
  75.         docTitle[0] = 31;
  76.  
  77.     BlockMove(&docTitle[0], &(*createdDocument)->documentTitle[0], (long) docTitle[0] +1);
  78.     newPage = 0;
  79.     err = MyInsertPage(*createdDocument, &newPage);
  80.     (*createdDocument)->curPage = newPage;
  81.  
  82. // Set the refCon to point to our document info structure.
  83.  
  84.     nrequire(err, CouldNotInsertPage);
  85.     SetWRefCon(documentWindow, (long) *createdDocument);
  86.     require(err, NoProblems);
  87.  
  88. CouldNotInsertPage:
  89.     DisposHandle((Handle) (*createdDocument)->documentPrintHdl);
  90.  
  91. CouldNotCreatePrintStuff:
  92.     DisposePtr((Ptr) *createdDocument);
  93.  
  94. CouldNotCreateDocRec:
  95.     DisposeWindow(documentWindow);
  96.  
  97. CouldNotCreateWindow:
  98. NoProblems:
  99.     return err;
  100. }
  101.  
  102.  
  103. /************************************************************
  104.   MyDisposeDocument - This routine is called when we need to
  105.   dispose of a window.
  106.  
  107. *************************************************************/
  108.  
  109. void MyDisposeDocument(MyDocumentPtr whichDocument)
  110. {
  111.     long        numPages, pg;
  112.     WindowPtr    docWindow;
  113.     
  114. // Dispose of our private data for each page of this document.
  115.  
  116.     numPages = whichDocument->numPages;
  117.  
  118.     for (pg = numPages; pg >= 1; pg--)
  119.         MyDisposePage(whichDocument, pg);
  120.  
  121. //    Dispose of our document's print record and private data.
  122.  
  123.     if (whichDocument->documentPrintHdl != nil)
  124.         DisposHandle((Handle) whichDocument->documentPrintHdl);
  125.     
  126.        DisposeWindow(whichDocument->documentWindow);
  127.     DisposePtr((Ptr) whichDocument);
  128. }
  129.  
  130.  
  131. /************************************************************
  132.   MyInsertPage - This routine is called when we need to add
  133.   a page to a document.  The page is added AFTER the page
  134.   number passed (1-based).  If whichPg is greater than the
  135.   last page of the document, the new page is added to the
  136.   end of the document.  If whichPg is less than 1, the page
  137.   is added to the beginning of the doc.  The page number of
  138.   the new page is returned in whichPg.
  139.  
  140. *************************************************************/
  141.  
  142. OSErr MyInsertPage(MyDocumentPtr whichDocument, long *whichPage)
  143. {
  144.     OSErr        err = noErr;
  145.     long        numPages, aPage;
  146.     long        newSize;
  147.  
  148. // Pin the number of the page to add to the range (1, numPages +1).
  149.  
  150.     numPages = whichDocument->numPages;
  151.     *whichPage = (*whichPage < 1)? 1: (*whichPage < numPages)? *whichPage +1: numPages +1;
  152.  
  153. /*
  154.     Do whatever you need to do to add page data here.
  155.     .
  156.     .
  157.     .
  158.     
  159. */
  160.  
  161.     numPages = ++whichDocument->numPages;
  162.     return err;
  163. }
  164.  
  165.  
  166. /************************************************************
  167.   MyDisposePage - This routine is called when we need to
  168.   dispose of a page in a document.
  169.  
  170. *************************************************************/
  171.  
  172. void MyDisposePage(MyDocumentPtr whichDocument, long whichPage)
  173. {
  174.     long        numPages, pageNum;
  175.     long        newSize;
  176.  
  177. // Idiot control.
  178.  
  179.     if (whichPage > whichDocument->numPages) return;    // ?!  There aren't that many pages!!
  180.     if (whichPage < 1) return;                            // ?!  Page numbers start at 1!!
  181.  
  182. /*
  183.     Do whatever you need to do to remove page data here.
  184.     .
  185.     .
  186.     .
  187.     
  188. */
  189.  
  190. // We now have one less page in our document.
  191.  
  192.     numPages = --whichDocument->numPages;
  193. }
  194.  
  195.  
  196. /************************************************************
  197.   MyUpdateWindow - This routine simply updates the passed
  198.   window.
  199.  
  200. *************************************************************/
  201.  
  202. void MyUpdateWindow(WindowPtr whichWindow)
  203. {
  204.     GrafPtr        oldPort;
  205.  
  206. // Update the indicated window.
  207.  
  208.     if (((WindowPeek) whichWindow)->windowKind == userKind)
  209.     {
  210.         GetPort(&oldPort);
  211.         SetPort(whichWindow);
  212.         BeginUpdate(whichWindow);
  213.         MyDrawContents(whichWindow);
  214.         EndUpdate(whichWindow);
  215.         SetPort(oldPort);
  216.     }
  217. }
  218.  
  219.  
  220. /************************************************************
  221.   MyDrawContents - This routine draws the contents of a
  222.   window.  Note that this same code is used to draw during
  223.   printing.  All we do in this code is make a bunch of
  224.   QuickDraw calls to draw our document's pages.
  225.  
  226. *************************************************************/
  227.  
  228. void MyDrawContents(WindowPtr whichWindow)
  229. {
  230.     MyDocumentPtr    windowDoc;
  231.     PicHandle        drawPict;
  232.     Rect            drawRect, drawRect2;
  233.     short            fNum, i, lineInc, hCenter, picWidth, picHeight;
  234.     short            oldResFile;
  235.     FontInfo        fInfo;
  236.     Handle            iconHdl;
  237.     BitMap            iconBitMap;
  238.     Str255            pStr;
  239.     Point            where;
  240.     GrafPtr            curPort;
  241.  
  242. //    Preserve the current resource file in case we're printing.
  243.  
  244.     oldResFile = CurResFile();
  245.     windowDoc = MyGetDocPtr(whichWindow);
  246.  
  247. // Draw a red QuickDraw rectangle.
  248.  
  249.     ForeColor(redColor);
  250.     SetRect(&drawRect, 20, 20, 150, 150);
  251.     FrameRect(&drawRect);
  252.  
  253. // Draw a blue QuickDraw oval.
  254.  
  255.     ForeColor(blueColor);
  256.     OffsetRect(&drawRect, 40, 40);
  257.     FrameOval(&drawRect);
  258.  
  259. // Draw a black QuickDraw line with a 4x4 pen.
  260.  
  261.     ForeColor(blackColor);
  262.     PenSize(4, 4);
  263.     MoveTo(drawRect.left, drawRect.top);
  264.     LineTo(drawRect.right, drawRect.bottom);
  265.     PenSize(1, 1);
  266.  
  267. // Draw some QuickDraw text with various faces.
  268.  
  269.     GetFNum("\pNew York", &fNum);
  270.     TextFont(fNum);
  271.     TextSize(10);
  272.     GetFontInfo(&fInfo);
  273.     lineInc = fInfo.ascent + fInfo.leading + fInfo.descent;
  274.     TextFace(bold);
  275.     MoveTo(220, 40);
  276.     DrawString("\pFor Sale: ");
  277.     TextFace(0);
  278.     DrawString("\pEnglish sheepdog.  ");
  279.     TextFace(underline);
  280.     DrawString("\pCompletely");
  281.     TextFace(0);
  282.     MoveTo(220, 40 + lineInc);
  283.     DrawString("\phouse-broken, eats a lot, ");
  284.     TextFace(italic);
  285.     DrawString("\ploves cats and");
  286.     MoveTo(220, 40 + 2* lineInc);
  287.     DrawString("\psmall children.");
  288.     TextFace(0);
  289.     DrawString("\p  Free to a good home.");
  290.     MoveTo(220, 40 + 3* lineInc);
  291.  
  292. // Draw two concentric QuickDraw rectangles around the text we just drew.
  293.  
  294.     GetPen(&where);
  295.     drawRect.left = 216;
  296.     drawRect.top = 30;
  297.     drawRect.right = 450;
  298.     drawRect.bottom = where.v - lineInc/2;
  299.     FrameRect(&drawRect);
  300.     InsetRect(&drawRect, -2, -2);
  301.     FrameRect(&drawRect);
  302.  
  303. /*
  304.     Calculate the center of our window, and then draw a
  305.     QuickDraw picture at that location.
  306. */
  307.  
  308.     hCenter = (whichWindow->portRect.right + whichWindow->portRect.left) >>1;
  309.  
  310.     UseResFile(gAppResRefNum);
  311.     drawPict = GetPicture(r_documentPict);
  312.     UseResFile(oldResFile);
  313.  
  314.     if (drawPict != nil) 
  315.     {
  316.         picWidth = (*drawPict)->picFrame.right - (*drawPict)->picFrame.left;
  317.         picHeight = (*drawPict)->picFrame.bottom - (*drawPict)->picFrame.top;
  318.         
  319.         drawRect.top = 240;
  320.         drawRect.left = hCenter -(picWidth >>1);
  321.         drawRect.bottom = drawRect.top + picHeight;
  322.         drawRect.right = drawRect.left + picWidth;
  323.          
  324.         DrawPicture(drawPict, &drawRect);
  325.         ReleaseResource((Handle) drawPict);
  326.     }
  327.  
  328. /*
  329.     Load a QuickDraw icon, and CopyBits a bunch of them across
  330.     the page, in various colors.
  331. */
  332.  
  333.     UseResFile(gAppResRefNum);
  334.     iconHdl = (Handle) GetIcon(r_documentBitmap);
  335.     UseResFile(oldResFile);
  336.  
  337.     if (iconHdl != nil)
  338.     {
  339.         MoveHHi((Handle) iconHdl);
  340.         HLock((Handle) iconHdl);
  341.         iconBitMap.rowBytes = 4;
  342.         SetRect(&iconBitMap.bounds, 0, 0, 31, 31);
  343.         iconBitMap.baseAddr = *iconHdl;
  344.         
  345.         drawRect.top = drawRect.bottom +20;
  346.         drawRect.left = 10;
  347.         drawRect.bottom = drawRect.top +31;
  348.         drawRect.right = drawRect.left +31;
  349.         
  350.         for (i = 0; i < 12; i++)
  351.         {
  352.             switch (i % 6)
  353.             {
  354.                 case 0:
  355.                     ForeColor(blackColor);
  356.                     break;
  357.                 case 1:
  358.                     ForeColor(blueColor);
  359.                     break;
  360.                 case 2:
  361.                     ForeColor(greenColor);
  362.                     break;
  363.                 case 3:
  364.                     ForeColor(redColor);
  365.                     break;
  366.                 case 4:
  367.                     ForeColor(cyanColor);
  368.                     break;
  369.                 case 5:
  370.                     ForeColor(magentaColor);
  371.                     break;
  372.             }
  373.             
  374.             GetPort(&curPort);
  375.             CopyBits(&iconBitMap, &curPort->portBits, &iconBitMap.bounds, &drawRect, srcCopy, nil);
  376.     
  377.             drawRect.left  += 40;
  378.             drawRect.right += 40;
  379.         }
  380.         
  381.         ReleaseResource(iconHdl);
  382.     }
  383.  
  384. // Draw some more QuickDraw text.  This time, blue and 24 point.
  385.  
  386.     GetFNum("\pTimes", &fNum);
  387.     TextFont(fNum);
  388.     TextSize(24);
  389.     ForeColor(blueColor);
  390.     // remove sprintf call, removes the need to link with the metrowerks ansi library
  391.     // was: pStr[0] = sprintf((char *) &pStr[1], "These are some typical QuickDraw objects");
  392.     
  393.     { 
  394.         unsigned char *tempStr = "\pThese are some typical QuickDraw objects" ;    // should come from a resource
  395.         BlockMove( &tempStr[1], &pStr[1], tempStr[0] ) ;
  396.         pStr[0] = tempStr[0] ;
  397.         
  398.  
  399.     }
  400.  
  401.     MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +20);
  402.     DrawString(pStr);
  403.  
  404. // Draw some QuickDraw PicComments.
  405.  
  406.     MyDrawPicComments();
  407.  
  408. /*
  409.     Draw some more black QuickDraw text in a different font
  410.     and size, indicating the page number.
  411. */
  412.     GetFNum("\pGeneva", &fNum);
  413.     TextFont(fNum);
  414.     TextSize(12);
  415.     
  416.     ForeColor(blackColor);
  417.     // remove sprintf call, removes the need to link with the metrowerks ansi library
  418.     // was: pStr[0] = sprintf((char *) &pStr[1], "This is page %ld of %ld.",
  419.     //                  windowDoc->curPage, windowDoc->numPages);
  420.  
  421.     {
  422.         unsigned char     *strPart1 = "\pThis is page " ;    // should come from a resource
  423.         unsigned char     *strPart2 = "\p of " ;            // should come from a resource
  424.         unsigned char    currentPage[32] ;
  425.         unsigned char    numberOfPages[32] ;
  426.         short    theLength = 0 ;
  427.         
  428.         NumToString( windowDoc->curPage, currentPage ) ;
  429.         NumToString( windowDoc->numPages, numberOfPages ) ;
  430.  
  431.         BlockMove( &strPart1[1], &pStr[theLength + 1], strPart1[0] ) ;
  432.         theLength += strPart1[0] ;
  433.         
  434.         BlockMove( ¤tPage[1], &pStr[theLength + 1], currentPage[0] ) ;
  435.         theLength += currentPage[0] ;
  436.         
  437.         BlockMove( &strPart2[1], &pStr[theLength + 1], strPart2[0] ) ;
  438.         theLength += strPart2[0] ;
  439.         
  440.         BlockMove( &numberOfPages[1], &pStr[theLength + 1], numberOfPages[0] ) ;
  441.         theLength += numberOfPages[0] ;
  442.         
  443.         pStr[0] = theLength ;
  444.         
  445.     }
  446.  
  447.     MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +80);
  448.     DrawString(pStr);
  449. }
  450.  
  451.  
  452. /************************************************************
  453.   MyDrawPicComments - This routine just draws some example
  454.   PicComments which will make a PostScript device display
  455.   "This was drawn on a PostScript device." and other devices
  456.   display "This was drawn on a non-PostScript device."  We
  457.   use PostScriptBegin PostScriptEnd and PostScriptHandle.
  458.  
  459. *************************************************************/
  460.  
  461. void MyDrawPicComments()
  462. {
  463.     short        fNum;
  464.  
  465. /*
  466.     Draw some QuickDraw to set the PS clip, not necessary in
  467.     this case, but if we hadn't made any QuickDraw calls yet,
  468.     the PostScript clip wouldn't get set, and *everything*
  469.     would be clipped.  This code, which doesn't actually draw
  470.     anything, is here as a reminder.
  471. */
  472.  
  473.     PenSize(0, 0);
  474.     MoveTo(0, 0); 
  475.     Line(0, 0);
  476.     PenSize(1, 1);
  477.  
  478. /*
  479.     PostScriptBegin tells a PostScript driver to ignore Quickdraw
  480.     calls until it receives a PostScriptEnd picture comment.
  481.     This line is ignored by non-PostScript printer drivers.
  482. */
  483.  
  484.     PicComment(PostScriptBegin, 0, nil);
  485.  
  486. /*
  487.     QuickDraw representation. These calls will only be executed by
  488.     QuickDraw printers.  Set the font to Times Italic 14 pt and then
  489.     move and draw.
  490. */
  491.  
  492.     GetFNum("\pTimes", &fNum);
  493.     TextFont(fNum);
  494.     TextSize(14);
  495.     TextFace(italic);
  496.     MoveTo(127, 227);
  497.     DrawString("\pThis was drawn on a non-PostScript device.");
  498.     TextFace(0);
  499.  
  500. /*
  501.     PostScript representation. These calls will only be executed by
  502.     PostScript printers.  We draw the same as above, sans the "non-"
  503.     and shifted left a tad.
  504. */
  505.  
  506.     MySendPostScript("\p0 760 translate 1 -1 scale");
  507.     MySendPostScript("\p/Times-Italic findfont 14 scalefont setfont");
  508.     MySendPostScript("\p135 533 moveto (This was drawn on a PostScript device.) show");
  509.  
  510. /*
  511.     PostScriptEnd tells a PostScript driver to start executing
  512.     QuickDraw calls normally again.
  513. */
  514.  
  515.     PicComment(PostScriptEnd, 0, nil);
  516. }
  517.  
  518.  
  519. /************************************************************
  520.   MySendPostScript - This routine just packages the passed
  521.   Pascal string into a handle and sends the PostScriptHandle
  522.   PicComment.
  523.  
  524. *************************************************************/
  525.  
  526. void MySendPostScript(Str255 thePostScript)
  527. {
  528.     OSErr    err;
  529.     Handle    thePSHdl;
  530.     Ptr        thePSPtr;
  531.     long    textLen;
  532.  
  533. /*
  534.     Create a handle for the passed string plus a carriage
  535.     return.  Move the string's data into the handle, stuff a
  536.     carriage return on the end, call PicComment, and finally
  537.     dispose of the handle.
  538. */
  539.     textLen = thePostScript[0];
  540.     thePSHdl = TempNewHandle(textLen +1, &err);
  541.  
  542.     if (!err)
  543.     {
  544.         thePSPtr = *thePSHdl;
  545.         BlockMove(&thePostScript[1], thePSPtr, textLen);
  546.         *(thePSPtr +textLen) = (char) 13; //carriage return.
  547.         ++textLen;
  548.  
  549.         PicComment(PostScriptHandle, textLen, thePSHdl);
  550.         DisposHandle(thePSHdl);
  551.     }
  552. }
  553.  
  554.  
  555. /************************************************************
  556.   MyAdjustMenus - This routine enables and disables our
  557.   menus and menu items.
  558.  
  559. *************************************************************/
  560.  
  561. void MyAdjustMenus()
  562. {
  563.     WindowPtr        activeWindow;
  564.     MenuHandle        appleMenu, fileMenu, editMenu, documentMenu;
  565.     MyDocumentPtr    activeDocument;
  566.     Boolean            docOpen, onFirstPage, onLastPage, maxPages, neverSaved;
  567.  
  568.     appleMenu = GetMHandle(mApple);
  569.     editMenu = GetMHandle(mEdit);
  570.     fileMenu = GetMHandle(mFile);
  571.     documentMenu = GetMHandle(mDocument);
  572.  
  573.     EnableItem(appleMenu, iAbout);
  574.     EnableItem(fileMenu,  iQuit);
  575.     EnableItem(fileMenu,  iNew);
  576.     EnableItem(fileMenu,  iOpen);
  577.  
  578. /*
  579.     If we have a document open, we enable certain menu items.
  580.     Otherwise, we don't.
  581. */
  582.  
  583.     activeWindow = FrontWindow();
  584.  
  585.     if (activeWindow)
  586.     {
  587.         if (((WindowPeek) activeWindow)->windowKind != userKind)
  588.             activeWindow = nil;
  589.     }
  590.  
  591.     docOpen = (activeWindow != nil);
  592.  
  593.     if (!docOpen)                                        // No document open.
  594.     {
  595.         DisableItem(fileMenu, iPrint);
  596.         DisableItem(fileMenu, iClose);
  597.         DisableItem(fileMenu, iSave);
  598.         DisableItem(fileMenu, iSaveAs);
  599.         DisableItem(fileMenu, iPageSetup);
  600.         DisableItem(documentMenu, iInsertPage);
  601.         DisableItem(documentMenu, iDeletePage);
  602.         DisableItem(documentMenu, iAheadPage);
  603.         DisableItem(documentMenu, iBackPage);
  604.     }
  605.     else                                                // A document is open.
  606.     {
  607.         EnableItem(fileMenu, iPrint);
  608.         EnableItem(fileMenu, iClose);
  609.         EnableItem(fileMenu, iPageSetup);
  610.         EnableItem(fileMenu, iSaveAs);
  611.  
  612. /*
  613.     Enable/disable items based on the number of pages in our document,
  614.     whether we're on the first or last page, and whether or not it's
  615.     been saved yet.
  616. */
  617.         activeDocument = MyGetDocPtr(activeWindow);
  618.  
  619.         if (activeDocument->numPages > 1)                // Got at least one page?
  620.             EnableItem(documentMenu, iDeletePage);
  621.         else
  622.             DisableItem(documentMenu, iDeletePage);
  623.  
  624.         onFirstPage = (activeDocument->curPage == 1);
  625.         onLastPage = (activeDocument->curPage == activeDocument->numPages);
  626.         maxPages = (activeDocument->numPages == kMaxPages);
  627.         neverSaved = (activeDocument->documentFSSpec.name[0] == 0);
  628.  
  629.         if (neverSaved)                                    // Never saved this document?
  630.             DisableItem(fileMenu, iSave);
  631.         else
  632.             EnableItem(fileMenu, iSave);
  633.  
  634.         if (!maxPages)                                    // Can still add more pages?
  635.             EnableItem(documentMenu, iInsertPage);
  636.         else
  637.             DisableItem(documentMenu, iInsertPage);
  638.  
  639.         if (!onLastPage)                                // Not on last page?
  640.             EnableItem(documentMenu, iAheadPage);
  641.         else
  642.             DisableItem(documentMenu, iAheadPage);
  643.  
  644.         if (!onFirstPage)                                // Not on first page?
  645.             EnableItem(documentMenu, iBackPage);
  646.         else
  647.             DisableItem(documentMenu, iBackPage);
  648.     }
  649. }
  650.  
  651.  
  652. /************************************************************
  653.   MyDoMenuCommand - This routine handles the dispatching of
  654.   our menu requests.
  655.  
  656. *************************************************************/
  657.  
  658. void MyDoMenuCommand(long menuResult)
  659. {
  660.     short                menuID, menuItem;
  661.     long                curPage, numPages, newPage;
  662.     Str255                daName;
  663.     OSErr                err;
  664.     WindowPtr            activeWindow;
  665.     MyDocumentPtr        activeDocument, aDocument;
  666.  
  667.     menuID = menuResult >>16;
  668.     menuItem = menuResult & 0x0000FFFF;
  669.     activeWindow = FrontWindow();
  670.     activeDocument = MyGetDocPtr(activeWindow);
  671.  
  672.     switch (menuID)
  673.     {
  674.         case mApple:
  675.             switch (menuItem)
  676.             {
  677.                 case iAbout:                    // About.
  678.  
  679.                     Alert(r_About, nil);
  680.                     break;
  681.                 
  682.                 default:                        // DAs, etc.
  683.  
  684.                     GetItem(GetMHandle(mApple), menuItem, daName);
  685.                     OpenDeskAcc(daName);
  686.                     break;
  687.             }
  688.             break;
  689.             
  690.             case mFile:
  691.                 switch (menuItem)
  692.                 {                        
  693.                     case iNew:                    // New or Open.
  694.                     case iOpen:
  695.  
  696.                         err = MyCreateDocument(kDefaultTitle, &aDocument);
  697.  
  698.                         if ((err == noErr) && (menuItem == iOpen))
  699.                         {
  700.                             err = MyLoadDocument(aDocument);
  701.  
  702.                             if (err != noErr)
  703.                                 MyDisposeDocument(aDocument);
  704.                         }
  705.                         
  706.                         if (err == noErr)
  707.                         {
  708.                             ShowWindow(aDocument->documentWindow);
  709.                             SelectWindow(aDocument->documentWindow);
  710.                             MyAdjustMenus();
  711.                         }
  712.                         break;
  713.                                                 
  714.                     case iClose:                // Close.
  715.  
  716.                         MyDisposeDocument(activeDocument);
  717.                         break;
  718.                                                 
  719.                     case iSave:                    // Save or Save As.
  720.                     case iSaveAs:
  721.  
  722.                         err = MySaveDocument(activeDocument, (menuItem == iSaveAs));
  723.                         break;
  724.         
  725.                     case iPageSetup:            // Page Setup.
  726.  
  727.                         if (MyDoPageSetup(activeDocument))
  728.                             MyRepaginateDoc(activeDocument);
  729.                         break;
  730.  
  731.                     case iPrint:                // Print.
  732.  
  733.                         err = MyPrintDocument(activeDocument);
  734.                         break;
  735.  
  736.                     case iQuit:                    // Quitting.
  737.  
  738.                         gQuitting = true;
  739.                         break;
  740.                 }
  741.                 break;
  742.                 
  743.             case mEdit:  // If this were a real app, blah, blah, blah.
  744.                 break;
  745.                 
  746.             case mDocument:
  747.                 switch (menuItem)
  748.                 {                        
  749.                     case iInsertPage:            // Insert a page.
  750.                             
  751.                             newPage = activeDocument->curPage;
  752.                             MyInsertPage(activeDocument, &newPage);
  753.                             activeDocument->curPage = newPage;
  754.                             SetPort(activeWindow);
  755.                             EraseRect(&activeWindow->portRect);
  756.                             InvalRect(&activeWindow->portRect);
  757.                         break;
  758.                                                 
  759.                     case iDeletePage:            // Delete current page.
  760.                             
  761.                             curPage = activeDocument->curPage;
  762.                             numPages = activeDocument->numPages;
  763.  
  764.                             if (numPages > 1)
  765.                             {
  766.                                 MyDisposePage(activeDocument, curPage);
  767.  
  768.                                 if (curPage == numPages)
  769.                                     curPage = --activeDocument->curPage;
  770.                                 
  771.                                 SetPort(activeWindow);
  772.                                 EraseRect(&activeWindow->portRect);
  773.                                 InvalRect(&activeWindow->portRect);
  774.                             }
  775.                         break;
  776.                                                 
  777.                     case iAheadPage:            // Display ahead one page.
  778.                             
  779.                             curPage = activeDocument->curPage;
  780.                             numPages = activeDocument->numPages;
  781.  
  782.                             if (curPage < numPages)
  783.                             {
  784.                                 ++activeDocument->curPage;
  785.                                 
  786.                                 SetPort(activeWindow);
  787.                                 EraseRect(&activeWindow->portRect);
  788.                                 InvalRect(&activeWindow->portRect);
  789.                             }
  790.                         break;
  791.                                                 
  792.                     case iBackPage:                // Display back one page.
  793.                             
  794.                             curPage = activeDocument->curPage;
  795.  
  796.                             if (curPage > 1)
  797.                             {
  798.                                 --activeDocument->curPage;
  799.                                 
  800.                                 SetPort(activeWindow);
  801.                                 EraseRect(&activeWindow->portRect);
  802.                                 InvalRect(&activeWindow->portRect);
  803.                             }
  804.                         break;
  805.                 }
  806.                 break;
  807.     }
  808.  
  809.     HiliteMenu(0);
  810. }
  811.  
  812.  
  813. /************************************************************
  814.   MyGetDocPtr - This routine returns a pointer to the
  815.   private document structure our application attaches to
  816.   its windows.
  817.  
  818. *************************************************************/
  819.  
  820. MyDocumentPtr MyGetDocPtr(WindowPtr whichWindow)
  821. {
  822.     MyDocumentPtr    windowsDocument = nil;
  823.  
  824.     if (whichWindow != nil)
  825.         windowsDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
  826.  
  827.     return windowsDocument;
  828. }
  829.  
  830.